package org.ordering;

import java.util.Comparator;

import javax.annotation.Nullable;

import com.google.common.base.Function;
import com.google.common.collect.Ordering;
import com.google.common.primitives.Ints;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args )
    {
        System.out.println( "Hello World!" );
        
        // 1.natural(); 创建排序器 , 对可排序类型做自然排序，如数字按大小，日期按先后排序
        Ordering<String> orderingOne = Ordering.natural();
        
        // 2.usingToString(); 按对象的字符串形式做字典排序[lexicographical ordering]
        Ordering<Object> orderingTwo = Ordering.usingToString();
        
        // 3.from(Comparator); 把给定的Comparator转化为排序器
        Ordering<String> orderingThree = Ordering.from(new Comparator<String>() {
			public int compare(String o1, String o2) {
				return 0;
			}
        });
        
        // 4.直接继承Ordering，实现自定义的排序器
        Ordering<String> byLengthOrdering = new Ordering<String>() {
			@Override
			public int compare(String left, String right) {
				return Ints.compare(left.length(), right.length());
			}
        };
        
        // 5.reverse() 获取语义相反的排序器
        Ordering<Object> reverseOrderingTwo = orderingTwo.reverse();
        
        // 6.nullsFirst() 使用当前排序器，但额外把null值排到最前面。
        Ordering<Object> nullsFirstOrderingTwo = orderingTwo.nullsFirst();
        
        // 7.nullsLast() 使用当前排序器，但额外把null值排到最后面
        Ordering<Object> nullsLastOrderingTwo = orderingTwo.nullsLast();
        
        // 8.compound(Comparator) 合成另一个比较器，以处理当前排序器中的相等情况
        Ordering<Object> compoundOrdering = orderingTwo.compound(new Comparator<Object>() {
			public int compare(Object o1, Object o2) {
				// TODO Auto-generated method stub
				return 0;
			}
        });
        
        // 9.lexicographical() 基于处理类型T的排序器，返回该类型的可迭代对象Iterable<T>的排序器
        Ordering<Iterable<Object>> iterableOrderingTwo = orderingTwo.lexicographical();
        
        // 10.onResultOf(Function) 对集合中元素调用Function，再按返回值用当前排序器排序。
        // 在guava中存在一个com.google.common.base.Functions和com.google.common.base.Function类，
        // 利用他们，可以为集合类的转换提供自定义的转换函数
        Function<Object, Object> function = new Function<Object, Object>() {
			public Object apply(Object input) {
				return input;
			}
        };
        Ordering<Object> onResultOfOrdering = orderingTwo.onResultOf(function);
        
        // 11. 练习
        // 当阅读链式调用产生的排序器时，应该从后往前读。上面的例子中，排序器首先调用apply方法获取sortedBy值，
        // 并把sortedBy为null的元素都放到最前面，然后把剩下的元素按sortedBy进行自然排序。之所以要从后往前读，是因为每次链式调用都是用后面的方法包装了前面的排序器。
        // 用compound方法包装排序器时，就不应遵循从后往前读的原则。为了避免理解上的混乱，请不要把compound写在一长串链式调用的中间，
        // 你可以另起一行，在链中最先或最后调用compound。
        Ordering<Foo> ordering = Ordering.natural().nullsFirst().onResultOf(new Function<Foo, String>() {
			public String apply(Foo input) {
				return input.sortedBy;
			}
        });
    }
    
    public static class Foo {
    	@Nullable
    	String sortedBy;
    	int notSortedBy;
    }
}
